/**
 * 演示 wait() 和 notiftyAll()
 */
public class WaitAndNotiftyAllExample {
    public static void main(String[] args) {

        // 定义一个锁对象
        Object locker = new Object();

        Thread thread1 = new Thread(() -> {
            try {
                // 上锁
                synchronized (locker) {
                    System.out.println(Thread.currentThread().getName() + " : 我要保卫祖国!!");
                    System.out.println(Thread.currentThread().getName() + " : 我将要在一秒后沉睡, 人们啊! 来唤醒我吧~");
                    Thread.sleep(1000);
                    locker.wait();
                    System.out.println(Thread.currentThread().getName() + " : 人民啊~ 我听到了你们的召唤!!!!!!");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "iron man~");


        Thread thread2 = new Thread(() -> {
            try {
                synchronized (locker) {
                    System.out.println(Thread.currentThread().getName() + " : 祖国正在被入侵, 我一定要将 iron man 唤醒, 让他来保卫祖国~");
                    System.out.println(Thread.currentThread().getName() + " : 我将在一秒锁唤醒 iron man~");
                    Thread.sleep(1000);
                    locker.notifyAll();
                }
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " : 我成功唤醒 iron man 了~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "人民");

        thread1.start();
        thread2.start();
    }
}

// wait() 和 notifyAll() 并不是线程的方法, 而是 Object 的方法, 这两个方法都必须在有锁的情况下才可以被执行
// wait() 会主动释放锁, 任务并阻塞在这个地方, 等待被唤醒之后再去竞争锁执行任务
// notifyAll() 唤醒所有在这个对象等待的线程
/**
 * iron man~ : 我要保卫祖国!!
 * iron man~ : 我将要在一秒后沉睡, 人们啊! 来唤醒我吧~
 * 人民 : 祖国正在被入侵, 我一定要将 iron man 唤醒, 让他来保卫祖国~
 * 人民 : 我将在一秒锁唤醒 iron man~
 * iron man~ : 人民啊~ 我听到了你们的召唤!!!!!!
 * 人民 : 我成功唤醒 iron man 了~
 */